/*
 * Advanced Methods in Programming 
 * Final Project: Pizza-on-line
 * 
 *   
 *   @author 309170249 317335214
 */
package mutual;

import java.io.Serializable;
import java.util.HashSet;

/**
 * Encapsulates all order relevant information
 */
public class Order implements Serializable {
	private static final long serialVersionUID = -8087763005006320604L;

	// Valid names for pizza toppings - adding for instance "Coke" is a matter
	// of putting it in array
	public static final String[] validExtrasNames = { "Olives", "Onions",
			"Mushrooms" };
	// O(1) searching structure for standard toppings
	private static final HashSet<String> validExtras = buildHash();

	// the price of pizza without any toppings
	private static final int basePrice = 40;
	// the price of a single extra
	private static final int extraPrice = 5;

	// note: We urge the client side to hashCode their names
	private final String clientName;
	// the id of this order (stays the same when order is updated)
	private String orderId;
	// the price of this order (changes when order is updated)
	private int price;
	// set of extras on top of this order
	private HashSet<String> extras;

	private boolean isNewOrder; //illegal order id
	/**
	 * Hiding default ctor
	 */
	private Order() {
		this.clientName = "";
	}

	/**
	 * Constructing new order - done on the client side
	 * 
	 * @param name
	 *            Clients name (preferably hashCoded) - immutable
	 */
	public Order(String name) {
		orderId = "";
		clientName = name;
		extras = new HashSet<String>();
		price = basePrice;
		isNewOrder = true;
	}

	/**
	 * Name getter
	 * 
	 * @return clients name set in ctor
	 */
	public String getClientName() {
		return clientName;
	}

	/**
	 * Ordered extras getter
	 * 
	 * @return the extras on top of this order
	 */
	public final HashSet<String> getExtras() {
		return this.extras;
	}

	/**
	 * Setting extras in a batch
	 * 
	 * @param extras
	 *            names of toppings
	 */
	public void setExtras(HashSet<String> extras) {
		// sanity check
		for (String s : extras)
			if (!validExtras.contains(s)) {
				System.out.println("Illegal extra " + s + " for order:"
						+ this.orderId);
				return;
			}

		this.extras = extras;
		calcPrice();
	}

	/**
	 * Price getter
	 * 
	 * @return the most updated price of pizza and all the toppings
	 */
	public int getPrice() {
		return price;
	}

	/**
	 * Setter for order uid !!! The client must never set the id, for he has no
	 * way to know it. !!! any id set by client would cause chaos in our pizza
	 * Server Hence - the security.
	 * 
	 * @param id
	 *            unique id on the server
	 * @param security
	 *            only the server (not the client!) knows the secret key that
	 *            enables setting orderID
	 * 
	 */
	public void setOrderId(String id, long security) {
		if (security == 317335214309170249L) {
			orderId = id;
			isNewOrder = false;
		}
		else
			System.out
					.println("Red alert, arm phasers! Resistance is futile! You will be assimilated");
	}
	
	/**
	 * Although client must never set the id of order,
	 * there are times, when she needs to set it to empty string
	 */
	public void initId() {
		isNewOrder = true;
	}
	
	/** 
	 * Getter for the status of order
	 * @return true when already running on server (id is set)
	 */
	public boolean isNew() {
		return isNewOrder;
	}
	
	/**
	 * Getter for the immutable orderId
	 * 
	 * @return
	 */
	public String getOrderId() {
		return orderId;
	}

	/**
	 * Calculates the price of order - sum of pizza and all the toppings
	 */
	private void calcPrice() {
		price = basePrice + extraPrice * extras.size();
	}

	/**
	 * Builds O(1) searching structure for toppings names.
	 * 
	 * @return Hash set with valid names for pizza toppings
	 */
	private static HashSet<String> buildHash() {
		HashSet<String> result = new HashSet<String>();
		for (String s : validExtrasNames)
			result.add(s);
		return result;
	}
}